Introdução

Análise exploratória de dados do RottenTomatoes sobre o ator Jake Gyllenhaal. O código empregado na extração dos dados aqui analizados e a descrição de como o usar encontra-se no repositório origem deste relatório.

  • Entradas que não contêm dados sobre bilheteria foram ignorados.




Data Overview

import_data("jake_gyllenhaal") 
filmes <- read_imported_data()
filmes %>% 
    glimpse()
Observations: 20
Variables: 5
$ avaliacao  <int> 92, 68, 73, 52, 73, 59, 82, 85, 92, 49, 35, 64, 47, 90, 87, 61, 62, 44, ...
$ filme      <chr> "Stronger", "Life", "Nocturnal Animals", "Demolition", "Everest", "South...
$ papel      <chr> "Jeff Bauman", "David Jordan", "Tony HastingsEdward Sheffield", "Davis M...
$ bilheteria <dbl> 4.2, 30.2, 10.7, 1.7, 46.6, 42.4, 61.0, 39.1, 54.7, 33.3, 90.8, 28.6, 9....
$ ano        <int> 2017, 2017, 2016, 2016, 2015, 2015, 2013, 2012, 2011, 2010, 2010, 2009, ...

Bilheteria

p <- filmes %>%
    ggplot(aes(x = ano, 
               y = bilheteria,
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m",
                            "\nAno:",ano))) + 
    geom_point(size = 4, color = paleta[1]) +
    labs(y = "Bilheteria", x = "Ano de lançamento")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Entre os filmes em que Jake atuou um foge aos outros em termos de faturamento, o memóravel blockbuster “O dia depois de amanhã” lançado em 2004.

  • É possível perceber uma tendência de queda no faturamento dos filmes em que Jake atuou após 2013.

filmes %>% 
    ggplot(aes(x = bilheteria)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = "grey", color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,200,20)) +
    labs(y = "Frequência Relativa", x = "Bilheteria")

  • Vemos claramente a disparidade entre “O dia depois de amanhã” e os outros filmes.

  • Nenhum valor fora do domínio de valores esperado, e.g. valores negativos.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = bilheteria,
               label = filme,
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m"))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Bilheteria")
ggplotly(p, tooltip="text") %>% 
    layout(autosize = F)
  • Separar os filmes entre os de bilheteria abaixo e acima de 50 milhões parece uma abordagem razoável.

  • “O dia depois de amanhã” aparenta formar um exército de um filme só. O que nos daria 3 grupos.

Avaliação

p <- filmes %>% 
    ggplot(aes(x = ano, 
               y = avaliacao,
                text = paste("Filme:",filme,
                            "\nAvaliação:",
                            avaliacao,
                            "\nAno:",ano))) + 
    geom_point(size = 4, color = paleta[1])  +
    scale_y_continuous(limits = c(0, 100)) +
    labs(y = "Avaliação RT", x = "Ano de lançamento")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Entre 2005 e 2010 Jake participou de uma série de filmes em particular que não agradou os críticos
  • Não aparenta haver uma tendência particularmente clara em razão do ano de lançamento.
filmes %>% 
    ggplot(aes(x = avaliacao)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = paleta[3], color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,100,10)) +
    labs(y = "Frequência Relativa", x = "Avaliação RT")

  • É possível perceber uma quantidade considerável de filmes com notas acima de 80.

  • Nenhum valor fora do domínio de valores esperado, e.g. valores negativos.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = avaliacao,
               text = paste(
                    "Filme:",filme,
                    "\nAvaliação:",avaliacao))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Avaliação RT")
ggplotly(p, tooltip = "text") %>% 
    layout(autosize = F)
  • Intuitivamente três grupos surgem:
    • Os filmes com avaliação acima de 80
    • Os filmes com avaliação entre 55 e 70
    • Os filmes com avaliação abaixo de 55




Agrupamento hierárquico

Uma dimensão

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (av=", avaliacao, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(avaliacao) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "ward.D")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) + 
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma")

get_grupos <- function(agrupamento, num_grupos){
    agrupamento %>% 
        cutree(num_grupos) %>% 
        as.data.frame() %>% 
        mutate(label = rownames(.)) %>% 
        gather(key =  "k", value = "grupo", -label) %>% 
        mutate(grupo = as.character(grupo))
}
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Filmes", y = avaliacao, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Avaliação RT", x = "", title = "Clusterização com uma Dimensão")

k_escolhido = 3
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, avaliacao),
               y = avaliacao,
               colour = grupo,
               text = paste(
                    "Filme:", reorder(label, avaliacao),
                    "\nAvaliação:", avaliacao,
                    "\nGrupo:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Avaliação RT") + 
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F)

Com duas dimensões

agrupamento_h_2d = filmes %>%
   mutate(bilheteria = log10(bilheteria)) %>%
   mutate_at(vars("avaliacao", "bilheteria"), funs(scale)) %>%
   column_to_rownames("filme") %>%
   select("avaliacao", "bilheteria") %>%
   dist(method = "euclidean") %>%
   hclust(method = "ward.D")
Setting row names on a tibble is deprecated.
ggdendrogram(agrupamento_h_2d, rotate = TRUE, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma")

filmes2 <- filmes %>%
    mutate(bilheteria = log10(bilheteria))
plota_hclusts_2d(agrupamento_h_2d,
                filmes2,
                c("avaliacao", "bilheteria"),
                linkage_method = "ward.D", 
                ks = 1:6,
                palette = "Dark2") + 
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação", title = "Clusterização com Duas Dimensões")

atribuicoes = get_grupos(agrupamento_h_2d, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    filter(k == 3) %>%
    mutate(filme = label) %>% 
    left_join(filmes, by = "filme")
p <- atribuicoes %>%
    ggplot(aes(x = avaliacao,
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Filme:", filme,
                    "\nBilheteria:", bilheteria,"m\n",
                    "Avaliação:", avaliacao))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação RT")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
LS0tCnRpdGxlOiAiVGlwb3MgZGUgZmlsbWUgZGUgSmFrZSBHeWxsZW5oYWFsIgphdXRob3I6ICJKb3PDqSBCZW5hcmRpIGRlIFNvdXphIE51bmVzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCiMjIEludHJvZHXDp8OjbwoKPiBBbsOhbGlzZSBleHBsb3JhdMOzcmlhIGRlIGRhZG9zIGRvIFtSb3R0ZW5Ub21hdG9lc10oaHR0cHM6Ly93d3cucm90dGVudG9tYXRvZXMuY29tLykgc29icmUgbyBhdG9yIEpha2UgR3lsbGVuaGFhbC4gTyBjw7NkaWdvIGVtcHJlZ2FkbyBuYSBleHRyYcOnw6NvIGRvcyBkYWRvcyBhcXVpIGFuYWxpemFkb3MgZSBhIGRlc2NyacOnw6NvIGRlIGNvbW8gbyB1c2FyIGVuY29udHJhLXNlIG5vICBbcmVwb3NpdMOzcmlvIG9yaWdlbV0oaHR0cHM6Ly9naXRodWIuY29tL0JlbmFyZGkvYWdydXBhbWVudG8tZmlsbWVzLykgZGVzdGUgcmVsYXTDs3Jpby4KCiogRW50cmFkYXMgcXVlIG7Do28gY29udMOqbSBkYWRvcyBzb2JyZSBiaWxoZXRlcmlhIGZvcmFtIGlnbm9yYWRvcy4KCjxicj4KCioqKgoKPGJyPgoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShnZ2RlbmRybykKCnNvdXJjZShoZXJlOjpoZXJlKCJjb2RlL2xpYi5SIikpCnNvdXJjZShoZXJlOjpoZXJlKCJjb2RlL3Bsb3RhX3NvbHVjb2VzX2hjbHVzdC5SIikpCgp0aGVtZV9zZXQodGhlbWVfcmVwb3J0KCkpCgprbml0cjo6b3B0c19jaHVuayRzZXQodGlkeSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoID0gNiwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQgPSA1LAogICAgICAgICAgICAgICAgICAgICAgZWNobyA9IFRSVUUpCnBhbGV0YSA9IGMoIiM0MDRFNEQiLAogICAgICAgICAgICIjOTJEQ0U1IiwKICAgICAgICAgICAiIzkzOEJBMSIsCiAgICAgICAgICAgIiMyRDMxNDIiLAogICAgICAgICAgICIjRjQ3NDNCIikKYGBgCgojIyBEYXRhIE92ZXJ2aWV3CgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQppbXBvcnRfZGF0YSgiamFrZV9neWxsZW5oYWFsIikgCmZpbG1lcyA8LSByZWFkX2ltcG9ydGVkX2RhdGEoKQpmaWxtZXMgJT4lIAogICAgZ2xpbXBzZSgpCmBgYAoKIyMjIEJpbGhldGVyaWEKCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUKICAgIGdncGxvdChhZXMoeCA9IGFubywgCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5CaWxoZXRlcmlhOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWxoZXRlcmlhLCJtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkFubzoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICsKICAgIGxhYnMoeSA9ICJCaWxoZXRlcmlhIiwgeCA9ICJBbm8gZGUgbGFuw6dhbWVudG8iKQoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogRW50cmUgb3MgZmlsbWVzIGVtIHF1ZSBKYWtlIGF0dW91IHVtIGZvZ2UgYW9zIG91dHJvcyBlbSB0ZXJtb3MgZGUgZmF0dXJhbWVudG8sIG8gbWVtw7NyYXZlbCBibG9ja2J1c3RlciAqKiJPIGRpYSBkZXBvaXMgZGUgYW1hbmjDoyIqKiBsYW7Dp2FkbyBlbSAyMDA0LgoKKiDDiSBwb3Nzw612ZWwgcGVyY2ViZXIgdW1hIHRlbmTDqm5jaWEgZGUgcXVlZGEgbm8gZmF0dXJhbWVudG8gZG9zIGZpbG1lcyBlbSBxdWUgSmFrZSBhdHVvdSBhcMOzcyAyMDEzLgoKYGBge3J9CmZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBiaWxoZXRlcmlhKSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PSguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSxiaW53aWR0aCA9IDEwLCBib3VuZGFyeSA9IDAsIAogICAgICAgICAgICAgICAgICAgZmlsbCA9ICJncmV5IiwgY29sb3IgPSAiYmxhY2siKSArIAogICAgZ2VvbV9ydWcoc2l6ZSA9IC41KSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDIwMCwyMCkpICsKICAgIGxhYnMoeSA9ICJGcmVxdcOqbmNpYSBSZWxhdGl2YSIsIHggPSAiQmlsaGV0ZXJpYSIpCgpgYGAKCiogVmVtb3MgY2xhcmFtZW50ZSBhIGRpc3BhcmlkYWRlIGVudHJlICoqIk8gZGlhIGRlcG9pcyBkZSBhbWFuaMOjIioqICBlIG9zIG91dHJvcyBmaWxtZXMuCgoqIE5lbmh1bSB2YWxvciBmb3JhIGRvIGRvbcOtbmlvIGRlIHZhbG9yZXMgZXNwZXJhZG8sIGUuZy4gdmFsb3JlcyBuZWdhdGl2b3MuCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIiIsCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICBsYWJlbCA9IGZpbG1lLAogICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5CaWxoZXRlcmlhOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWxoZXRlcmlhLCJtIikpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDUsIGFscGhhID0gLjMsIHNpemUgPSAzKSArIAogICAgbGFicyh4ID0gIiIsIHk9IkJpbGhldGVyaWEiKQoKZ2dwbG90bHkocCwgdG9vbHRpcD0idGV4dCIpICU+JSAKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAoKKiBTZXBhcmFyIG9zIGZpbG1lcyBlbnRyZSBvcyBkZSBiaWxoZXRlcmlhIGFiYWl4byBlIGFjaW1hIGRlIDUwIG1pbGjDtWVzIHBhcmVjZSB1bWEgYWJvcmRhZ2VtIHJhem/DoXZlbC4KCiogKioiTyBkaWEgZGVwb2lzIGRlIGFtYW5ow6MiKiogYXBhcmVudGEgZm9ybWFyIHVtIGV4w6lyY2l0byBkZSB1bSBmaWxtZSBzw7MuIE8gcXVlIG5vcyBkYXJpYSAzIGdydXBvcy4gCgojIyMgQXZhbGlhw6fDo28KCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhbm8sIAogICAgICAgICAgICAgICB5ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKCJGaWxtZToiLGZpbG1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuQXZhbGlhw6fDo286IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF2YWxpYWNhbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkFubzoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArCiAgICBsYWJzKHkgPSAiQXZhbGlhw6fDo28gUlQiLCB4ID0gIkFubyBkZSBsYW7Dp2FtZW50byIpCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAoKKiBFbnRyZSAyMDA1IGUgMjAxMCBKYWtlIHBhcnRpY2lwb3UgZGUgdW1hIHPDqXJpZSBkZSBmaWxtZXMgZW0gcGFydGljdWxhciBxdWUgbsOjbyBhZ3JhZG91IG9zIGNyw610aWNvcyAKKiBOw6NvIGFwYXJlbnRhIGhhdmVyIHVtYSB0ZW5kw6puY2lhIHBhcnRpY3VsYXJtZW50ZSBjbGFyYSBlbSByYXrDo28gZG8gYW5vIGRlIGxhbsOnYW1lbnRvLiAKCmBgYHtyfQpmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYXZhbGlhY2FvKSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PSguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSxiaW53aWR0aCA9IDEwLCBib3VuZGFyeSA9IDAsIAogICAgICAgICAgICAgICAgICAgZmlsbCA9IHBhbGV0YVszXSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgZ2VvbV9ydWcoc2l6ZSA9IC41KSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEwMCwxMCkpICsKICAgIGxhYnMoeSA9ICJGcmVxdcOqbmNpYSBSZWxhdGl2YSIsIHggPSAiQXZhbGlhw6fDo28gUlQiKQoKYGBgCgoqIMOJIHBvc3PDrXZlbCBwZXJjZWJlciB1bWEgcXVhbnRpZGFkZSBjb25zaWRlcsOhdmVsIGRlIGZpbG1lcyBjb20gbm90YXMgYWNpbWEgZGUgODAuCgoqIE5lbmh1bSB2YWxvciBmb3JhIGRvIGRvbcOtbmlvIGRlIHZhbG9yZXMgZXNwZXJhZG8sIGUuZy4gdmFsb3JlcyBuZWdhdGl2b3MuCgoKYGBge3J9CnAgPC0gZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoeCA9ICIiLAogICAgICAgICAgICAgICB5ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoCiAgICAgICAgICAgICAgICAgICAgIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgIlxuQXZhbGlhw6fDo286IixhdmFsaWFjYW8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjA1LCBhbHBoYSA9IC4zLCBzaXplID0gMykgKyAKICAgIGxhYnMoeCA9ICIiLCB5PSJBdmFsaWHDp8OjbyBSVCIpCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUgCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQoKYGBgCgoqIEludHVpdGl2YW1lbnRlIHRyw6pzIGdydXBvcyBzdXJnZW06CiAgICAqIE9zIGZpbG1lcyBjb20gYXZhbGlhw6fDo28gYWNpbWEgZGUgODAKICAgICogT3MgZmlsbWVzIGNvbSBhdmFsaWHDp8OjbyBlbnRyZSA1NSBlIDcwIAogICAgKiBPcyBmaWxtZXMgY29tIGF2YWxpYcOnw6NvIGFiYWl4byBkZSA1NQoKPGJyPgoKKioqCgo8YnI+CgojIyBBZ3J1cGFtZW50byBoaWVyw6FycXVpY28KCiMjIyBVbWEgZGltZW5zw6NvCgpgYGB7cn0KYWdydXBhbWVudG9faCA9IGZpbG1lcyAlPiUgCiAgICBtdXRhdGUobm9tZSA9IHBhc3RlMChmaWxtZSwgIiAoYXY9IiwgYXZhbGlhY2FvLCAiKSIpKSAlPiUgCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JSAKICAgIHNlbGVjdChhdmFsaWFjYW8pICU+JQogICAgZGlzdChtZXRob2QgPSAiZXVjbGlkaWFuIikgJT4lIAogICAgaGNsdXN0KG1ldGhvZCA9ICJ3YXJkLkQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2gsIHJvdGF0ZSA9IFQsIHNpemUgPSAyLCB0aGVtZV9kZW5kcm8gPSBGKSArIAogICAgbGFicyh5ID0gIkRpc3NpbWlsYXJpZGFkZSIsIHggPSAiIiwgdGl0bGUgPSAiRGVuZHJvZ3JhbWEiKQpgYGAKCmBgYHtyfQpnZXRfZ3J1cG9zIDwtIGZ1bmN0aW9uKGFncnVwYW1lbnRvLCBudW1fZ3J1cG9zKXsKICAgIGFncnVwYW1lbnRvICU+JSAKICAgICAgICBjdXRyZWUobnVtX2dydXBvcykgJT4lIAogICAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICAgICAgbXV0YXRlKGxhYmVsID0gcm93bmFtZXMoLikpICU+JSAKICAgICAgICBnYXRoZXIoa2V5ID0gICJrIiwgdmFsdWUgPSAiZ3J1cG8iLCAtbGFiZWwpICU+JSAKICAgICAgICBtdXRhdGUoZ3J1cG8gPSBhcy5jaGFyYWN0ZXIoZ3J1cG8pKQp9CgphdHJpYnVpY29lcyA9IGdldF9ncnVwb3MoYWdydXBhbWVudG9faCwgbnVtX2dydXBvcyA9IDE6NikKCmF0cmlidWljb2VzID0gYXRyaWJ1aWNvZXMgJT4lIAogICAgbGVmdF9qb2luKGZpbG1lcywgYnkgPSBjKCJsYWJlbCIgPSAiZmlsbWUiKSkKCmF0cmlidWljb2VzICU+JSAKICAgIGdncGxvdChhZXMoeCA9ICJGaWxtZXMiLCB5ID0gYXZhbGlhY2FvLCBjb2xvdXIgPSBncnVwbykpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wMiwgaGVpZ2h0ID0gMCwgc2l6ZSA9IDEuNiwgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBsYWJzKHkgPSAiQXZhbGlhw6fDo28gUlQiLCB4ID0gIiIsIHRpdGxlID0gIkNsdXN0ZXJpemHDp8OjbyBjb20gdW1hIERpbWVuc8OjbyIpCgpgYGAKCmBgYHtyfQprX2VzY29saGlkbyA9IDMKCnAgPC1hdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSBrX2VzY29saGlkbykgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihsYWJlbCwgYXZhbGlhY2FvKSwKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgcmVvcmRlcihsYWJlbCwgYXZhbGlhY2FvKSwKICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICAgICAgIlxuR3J1cG86IiwgZ3J1cG8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgbGFicyh4ID0gIiIsIHkgPSAiQXZhbGlhw6fDo28gUlQiKSArIAogICAgY29vcmRfZmxpcCgpCgpnZ3Bsb3RseShwLHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRikKCmBgYAoKIyMjIENvbSBkdWFzIGRpbWVuc8O1ZXMKCmBgYHtyfQphZ3J1cGFtZW50b19oXzJkID0gZmlsbWVzICU+JQogICBtdXRhdGUoYmlsaGV0ZXJpYSA9IGxvZzEwKGJpbGhldGVyaWEpKSAlPiUKICAgbXV0YXRlX2F0KHZhcnMoImF2YWxpYWNhbyIsICJiaWxoZXRlcmlhIiksIGZ1bnMoc2NhbGUpKSAlPiUKICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JQogICBzZWxlY3QoImF2YWxpYWNhbyIsICJiaWxoZXRlcmlhIikgJT4lCiAgIGRpc3QobWV0aG9kID0gImV1Y2xpZGVhbiIpICU+JQogICBoY2x1c3QobWV0aG9kID0gIndhcmQuRCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faF8yZCwgcm90YXRlID0gVFJVRSwgdGhlbWVfZGVuZHJvID0gRikgKwogICAgbGFicyh5ID0gIkRpc3NpbWlsYXJpZGFkZSIsIHggPSAiIiwgdGl0bGUgPSAiRGVuZHJvZ3JhbWEiKQpgYGAKCmBgYHtyfQpmaWxtZXMyIDwtIGZpbG1lcyAlPiUKICAgIG11dGF0ZShiaWxoZXRlcmlhID0gbG9nMTAoYmlsaGV0ZXJpYSkpCgpwbG90YV9oY2x1c3RzXzJkKGFncnVwYW1lbnRvX2hfMmQsCiAgICAgICAgICAgICAgICBmaWxtZXMyLAogICAgICAgICAgICAgICAgYygiYXZhbGlhY2FvIiwgImJpbGhldGVyaWEiKSwKICAgICAgICAgICAgICAgIGxpbmthZ2VfbWV0aG9kID0gIndhcmQuRCIsIAogICAgICAgICAgICAgICAga3MgPSAxOjYsCiAgICAgICAgICAgICAgICBwYWxldHRlID0gIkRhcmsyIikgKyAKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSIsIHggPSAiQXZhbGlhw6fDo28iLCB0aXRsZSA9ICJDbHVzdGVyaXphw6fDo28gY29tIER1YXMgRGltZW5zw7VlcyIpCmBgYAoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oXzJkLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSAzKSAlPiUKICAgIG11dGF0ZShmaWxtZSA9IGxhYmVsKSAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9ICJmaWxtZSIpCgpwIDwtIGF0cmlidWljb2VzICU+JQogICAgZ2dwbG90KGFlcyh4ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgIlxuQmlsaGV0ZXJpYToiLCBiaWxoZXRlcmlhLCJtXG4iLAogICAgICAgICAgICAgICAgICAgICJBdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh5ID0gIkJpbGhldGVyaWEiLCB4ID0gIkF2YWxpYcOnw6NvIFJUIikKCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAo=